package com.school.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.school.domain.dto.order.OrderAddDTO;
import com.school.domain.dto.order.OrderDetailDTO;
import com.school.domain.dto.order.SelectOrderDTO;
import com.school.domain.dto.order.UpdateOrderDTO;
import com.school.domain.po.Order;
import com.school.domain.po.OrderProduct;
import com.school.domain.vo.PageVO;
import com.school.domain.vo.order.*;
import com.school.mapper.OrderDao;
import com.school.mapper.OrderProductDao;
import com.school.service.OrderProductService;
import com.school.service.OrderService;
import jakarta.annotation.Resource;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 订单主表 服务实现类
 * </p>
 *
 * @author Forever
 * @since 2025-07-05
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderDao, Order> implements OrderService {
    @Resource
    private OrderProductDao orderProductDao;
    @Resource
    private OrderDao orderDao;
    @Resource
    private OrderProductService orderProductService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;


    private void saveOP(OrderDetailDTO item, @NotNull Long orderId, @NotNull LocalDateTime orderDatetime) {
        // 保存订单产品
        OrderProduct orderProduct = BeanUtil
                .copyProperties(item, OrderProduct.class)
                .setSkuCode(item.getProductId())
                .setOrderDatetime(orderDatetime)
                .setOrderId(orderId);
        // 保存订单产品
        boolean saveOp = orderProductService.save(orderProduct);
        // 更新订单总量
        stringRedisTemplate.opsForValue().increment("totalRolls:" + orderId, item.getRolls());
        // 判断保存订单产品是否成功
        if (!saveOp) throw new RuntimeException("保存订单产品失败");
    }
    //=======业务代码==========

    @Override
    public PageVO<Order> queryOrder(@NotNull SelectOrderDTO selectOrderDTO) {
        Page<Order> orderPage = lambdaQuery()
                // 订单编号
                .eq(selectOrderDTO.getOrderId() != null, Order::getOrderId, selectOrderDTO.getOrderId())
                // 用户名
                .like(!StrUtil.isEmpty(selectOrderDTO.getUserName()), Order::getUserName, selectOrderDTO.getUserName())
                // 手机号码
                .like(!StrUtil.isEmpty(selectOrderDTO.getPhone()), Order::getPhone, selectOrderDTO.getPhone())
                // 订单类型
                .eq(!StrUtil.isEmpty(selectOrderDTO.getOrderType()), Order::getOrderType, selectOrderDTO.getOrderType())
                // 小于下单结束时间
                .le(selectOrderDTO.getOrderTimeEnd() != null, Order::getOrderDate, selectOrderDTO.getOrderTimeEnd())
                // 大于下单开始时间
                .ge(selectOrderDTO.getOrderTimeStart() != null, Order::getOrderDate, selectOrderDTO.getOrderTimeStart())
                // 大于下单开始时间
                .ge(selectOrderDTO.getOrderDateStart() != null, Order::getOrderTime, selectOrderDTO.getOrderDateStart())
                // 小于下单结束时间
                .le(selectOrderDTO.getOrderDateEnd() != null, Order::getOrderTime, selectOrderDTO.getOrderDateEnd())
                // 小于出库总量
                .le(selectOrderDTO.getTotalRollsEnd() != null, Order::getTotalRolls, selectOrderDTO.getTotalRollsEnd())
                // 大于出库总量
                .ge(selectOrderDTO.getTotalRollsStart() != null, Order::getTotalRolls, selectOrderDTO.getTotalRollsStart())
                // 按照下单时间倒序
                .orderByDesc(Order::getOrderDate, Order::getOrderTime)
                // 分页
                .page(new Page<>(selectOrderDTO.getPageNum(), selectOrderDTO.getPageSize()));
        return PageVO.MPPageToPageVO(orderPage);
    }

    @Override
    @Transactional
    public String updateOrder(UpdateOrderDTO updateOrderDTO) {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM-dd")
                .toFormatter();
        LocalDate date = LocalDate.parse(updateOrderDTO.getOrderDate(), formatter);
        boolean isUpdate = lambdaUpdate()
                // 订单编号
                .eq(updateOrderDTO.getOrderId() != null, Order::getOrderId, updateOrderDTO.getOrderId())
                // 用户名
                .set(StrUtil.isNotEmpty(updateOrderDTO.getUserName()), Order::getUserName, updateOrderDTO.getUserName())
                // 手机号码
                .set(StrUtil.isNotEmpty(updateOrderDTO.getPhone()), Order::getPhone, updateOrderDTO.getPhone())
                // 订单类型
                .set(updateOrderDTO.getOrderDate() != null, Order::getOrderDate, date)
                // 下单时间
                .set(updateOrderDTO.getOrderTime() != null, Order::getOrderTime, updateOrderDTO.getOrderTime())
                // 出库总量
                .set(StrUtil.isNotEmpty(updateOrderDTO.getOrderType()), Order::getOrderType, updateOrderDTO.getOrderType())
                .update();

        // 如果修改了订单日期或时间，需要同步更新订单产品关联表的order_datetime字段
        if (isUpdate && (updateOrderDTO.getOrderDate() != null || updateOrderDTO.getOrderTime() != null)) {
            // 获取更新后的订单信息
            Order updatedOrder = getById(updateOrderDTO.getOrderId());
            if (updatedOrder != null) {
                // 拼接订单日期和时间为LocalDateTime
                LocalDateTime orderDatetime = LocalDateTime.of(updatedOrder.getOrderDate(), updatedOrder.getOrderTime());
                // 更新订单产品关联表的order_datetime字段
                orderProductService.lambdaUpdate()
                        .eq(OrderProduct::getOrderId, updateOrderDTO.getOrderId())
                        .set(OrderProduct::getOrderDatetime, orderDatetime)
                        .update();
            }
        }

        return isUpdate ? "修改成功" : "修改失败";
    }

    @Override
    public List<OrderDetailsVO> getOrderDetails(Long orderId) {
        if (orderId == null) throw new RuntimeException("订单编号不能为空");
        return orderProductDao.getOrderDetails(orderId);
    }

    @Override
    @Transactional
    public String saveAddDTO(OrderAddDTO orderAddDTO) {
        DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .appendPattern("yyyy-MM-dd")
                .toFormatter();
        LocalDate date = LocalDate.parse(orderAddDTO.getOrderDate(), formatter);
        Order order = BeanUtil.copyProperties(orderAddDTO, Order.class, "orderDate").setOrderDate(date);
        boolean save = save(order);
        Long orderId = order.getOrderId();
        if (!save) throw new RuntimeException("保存订单失败");
        int totalRolls = 0;
        // 计算订单总量
        stringRedisTemplate.opsForValue().set("totalRolls:" + order.getOrderId(), String.valueOf(totalRolls));
        // 拼接订单日期和时间为LocalDateTime
        LocalTime time = LocalTime.parse(orderAddDTO.getOrderTime());
        LocalDateTime orderDatetime = LocalDateTime.of(order.getOrderDate(), time);
        // 保存订单产品关联
        orderAddDTO.getOrderDetailList()
                .forEach(item -> saveOP(item, orderId, orderDatetime));
        // 获取订单总量
        totalRolls = Integer.parseInt(Objects.requireNonNull(stringRedisTemplate
                .opsForValue()
                .getAndDelete("totalRolls:" + orderId)));
        // 更新订单总量
        boolean update = lambdaUpdate()
                .eq(Order::getOrderId, orderId)
                .set(Order::getTotalRolls, totalRolls)
                .update();
        return update ? "保存订单成功" : "保存订单失败";
    }

    @Override
    @Transactional
    public String deleteOrder(Long orderId) {
        if (orderId == null) throw new RuntimeException("订单编号不能为空");
        boolean remove = remove(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderId, orderId));
        boolean removeOP = orderProductService.remove(new LambdaQueryWrapper<OrderProduct>()
                .eq(OrderProduct::getOrderId, orderId));
        if (!remove || !removeOP) throw new RuntimeException("删除订单失败");
        return "删除订单成功";
    }

    @Override
    public LargeScreenShowVO queryLargeScreenData(String yearMonth) {
        //获取订单数据
        LargeScreenVO largeScreenVO = orderDao.getLargeScreenCountAndRoll(yearMonth);
        //获取订单产品数据
        List<LargeScreenCargoVO> cargoRank = orderDao.getCargoRank(yearMonth, 6);
        LargeScreenCargoNumVO largeScreenCargo1 = orderDao.getLargeScreenCargo(yearMonth);
        Long largeScreenCargo = largeScreenCargo1 == null ? 0L : largeScreenCargo1.getSkuCount();
        //获取订单类别饼状图数据
        List<LargeScreenPieVO> pieVO = orderDao.getLargeScreenPie(yearMonth);
        // 获取订单类别折线图数据
        List<LargeScreenLineVO> lineVO = orderDao.getLineLargeScreen(yearMonth.split("-")[1], yearMonth.split("-")[0]);
        return new LargeScreenShowVO()
                // 可视化大屏的几个方框数据
                .setLargeScreenVO(largeScreenVO)
                // 货物排行榜数据
                .setLargeScreenCargoVO(cargoRank)
                // 订单类别饼状图数据
                .setLargeScreenPieVOs(pieVO)
                // 订单类别折线图数据
                .setLargeScreenLineVOs(lineVO)
                .setCargoCount(largeScreenCargo);
    }


}
